home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1999 November / Macworld (1999-11).dmg / Updaters / WhiteCap 3.0.4 / WhiteCap Source.sit / WhiteCap Source / WhiteCapWorld.cpp < prev    next >
C/C++ Source or Header  |  1999-08-28  |  16KB  |  610 lines

  1. #include "WhiteCapWorld.h"
  2.  
  3. // Praise Jesus! I can't keep quiet...Ye-haw!
  4.  
  5. #include "Sample.h"
  6. #include "CEgIFile.h"
  7. #include "ArgList.h"
  8. #include "R3Matrix.h"
  9.  
  10. #if EG_MAC
  11. #include <Dialogs.h>
  12.  
  13.  
  14. #endif
  15.  
  16. #if EG_WIN
  17. #include "RectUtils.h"
  18. #endif
  19.  
  20. #include "PixPort.h"
  21. #include "EgOSUtils.h"
  22. #include "CEgFileSpec.h"
  23.  
  24.  
  25. WhiteCapWorld::WhiteCapWorld()  {
  26.     
  27.     mSamples        = NULL;
  28.     mRecentSample    = NULL;
  29.     mWave            = NULL;
  30.     mTransitionTime    = -1;
  31.     mPi                = 3.1415926535897;
  32.     mCurBackClr        = -1;        // This will cause an update to mCurBackClr in Render()
  33.     mNumSampleBins    = NUM_SAMPLE_BINS;
  34.     
  35.     mDict.AddVar( "S", &mS );
  36.     mDict.AddVar( "T", &mT );
  37.     mDict.AddVar( "ST", &mST );
  38.     mDict.AddVar( "DT", &mDT );
  39.     mDict.AddVar( "PI", &mPi );
  40.     mDict.AddVar( "NUM_SAMPLE_BINS", &mNumSampleBins );        // Let user read num sample bins if they want
  41.     mDict.AddVar( "BASS1", &mBass1 );
  42.     mDict.AddVar( "BASS2", &mBass2 );
  43.     mDict.AddVar( "BASS3", &mBass3 );
  44.     mDict.AddFcn( "MAG", &mMagPtr, NUM_SAMPLE_BINS );
  45.  
  46.  
  47.     SetRect( &mPaneRect, 5000, 5000, -5000, -5000 );
  48.             
  49.     mLastSampleTime = EgOSUtils::CurTimeMS();
  50. }
  51.  
  52.  
  53.  
  54. WhiteCapWorld::~WhiteCapWorld() {
  55.     Sample *sample;
  56.     
  57.     // Move all the sample to the mFreeList
  58.     ExpireSamples();
  59.     
  60.     // Delete all the sample from the free list
  61.     while ( mFreeList.FetchLast( &sample ) ) {
  62.         delete sample;
  63.         mFreeList.RemoveLast();
  64.     }
  65. }
  66.  
  67.  
  68.  
  69.  
  70.  
  71. #define __FACTORY    "\
  72. Resn=10,\
  73. Durn=\".8\",\
  74. CamX=\"59*cos(t/6)\",\
  75. CamY=\"50*sin(t/7)\",\
  76. CamZ=\"25 + 10*cos(t/13)\",\
  77. CmLX=\"40\",CmLY=\"0\",CmLZ=\"0\",\
  78. CUpX=\"0\",CUpY=\"0\",CUpZ=\"1\",\
  79. R=\"0\",G=\"1-dt\",B=\"0\",\
  80. LvlR=\"1\",LvlG=\"0\",LvlB=\"0\",\
  81. widt=320,heig=300,\
  82. ConL=1,ConB=1,\
  83. Fall=\"0.035\",\
  84. X=\"100*dt\",Y=\"130*s-65\",Z=\"20*abs( mag( s ) )\",\
  85. Scal=\"600\",\
  86. ScSz=1,\
  87. Vers=30,\
  88. Pers=\"350\""
  89.  
  90.  
  91.  
  92.  
  93.  
  94. void WhiteCapWorld::Init( const CEgFileSpec* inConfig, long inTransitionTime ) {
  95.     CEgIFile file;
  96.     int ok, vers;
  97.     UtilStr        str, configText, num;
  98.     ArgList        args;
  99.     
  100.     file.open( inConfig );
  101.     args.SetArgs( &file );
  102.     ok = file.noErr();
  103.     if ( ok ) {
  104.         vers = args.GetArg( 'Vers' );
  105.         ok = vers == 30;
  106.     }
  107.  
  108.     // If something went wrong or we have an earlier version, default to the factory config    
  109.     if ( ! ok ) {
  110.         args.Clear();
  111.         args.SetArgs( __FACTORY );
  112.     }
  113.         
  114.     mTransitionTime = inTransitionTime;
  115.     mTransitionEnd = EgOSUtils::CurTimeMS() + mTransitionTime;
  116.  
  117.     // If first time load, don't do any transition
  118.     if ( mWave == NULL ) {
  119.         mWave = &mWave1;
  120.         mNextWave = &mWave2;
  121.         mWave -> Assign( args, mDict );
  122.         mTransitionTime = -1;  
  123.         inConfig -> GetFileName( mWave -> mTitle );  }
  124.     else {
  125.         mNextWave -> Assign( args, mDict );
  126.         mWave -> SetupTransition( mNextWave, &mTransitionT );
  127.         inConfig -> GetFileName( mNextWave -> mTitle );
  128.     }
  129.     
  130. }
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137. void WhiteCapWorld::SetPaneRect( const Rect& inRect ) {
  138.     int width = inRect.right - inRect.left;
  139.     int heigt = inRect.bottom - inRect.top;
  140.     
  141.     mPaneRect = inRect;
  142.     
  143.     // Besure we erase the new rect are next time
  144.     mRenderedRect = mPaneRect;
  145.     
  146.     // Invaliadate this rect till later...
  147.     ::SetRect( &mTitleRect, 0, 0, 0, 0 );
  148.     
  149.     // If the scale changes with window size
  150.     mWave -> SetScaleToFit( width, heigt );
  151.     mNextWave -> SetScaleToFit( width, heigt );
  152. }
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161. #define __Chk( xx, yy ) x = xx; y = yy;                        \
  162.                         if ( x >= mRenderedRect.right )        \
  163.                             mRenderedRect.right = x+1;        \
  164.                         if ( x <= mRenderedRect.left )        \
  165.                             mRenderedRect.left = x-1;        \
  166.                         if ( y >= mRenderedRect.bottom )    \
  167.                             mRenderedRect.bottom = y+1;        \
  168.                         if ( y <= mRenderedRect.top )        \
  169.                             mRenderedRect.top = y-1;    
  170.  
  171.  
  172. #define _evalClr( var, clr )    { clrTemp = 65534.9 * mWave -> clr.Evaluate();  if ( clrTemp < 0 ) clrTemp = 0; if ( clrTemp <= 0xFFFF ) var = clrTemp; else var = 0xFFFF;        }
  173.     
  174.  
  175. // Pre: Render() was called before this
  176. void WhiteCapWorld::DrawConfigName( void* inPort ) {
  177.     RGBColor clr;
  178.     float w;
  179.     unsigned char* str;
  180.         
  181.     // Save the current mac port.  Even Win9X/NT is crap, it's APIs/Interfaces are pretty decent, namely the GDI stuff.
  182.     // But sure, then again, if an OS designed for 1984ish cpus can compete w/ a 'modern' OS, i'd be damned
  183.     // ashamed if i was on the Win implementation team...  
  184.     #if EG_MAC
  185.      GrafPtr    savePort;
  186.     ::GetPort( &savePort );
  187.     ::SetPort( (GrafPtr) inPort );                
  188.     ::TextFont( 20 );
  189.     ::TextSize( 12 );
  190.     #endif
  191.     
  192.     #if EG_WIN
  193.     HDC hdc = ::GetDC( (HWND) inPort );
  194.     #endif
  195.     
  196.     mTitleRect.left = mPaneRect.left;
  197.     mTitleRect.bottom = mPaneRect.bottom;
  198.     mTitleRect.top = mPaneRect.bottom - 20;
  199.     
  200.     if ( mTransitionTime > 0 ) {
  201.  
  202.         if ( mTransitionT > .5 ) {
  203.             w = 2 * mTransitionT - 1;
  204.             str = mWave -> mTitle.getPasStr(); }
  205.         else {
  206.             w = 1 - 2 * mTransitionT;
  207.             str = mNextWave -> mTitle.getPasStr(); 
  208.         }
  209.             
  210.         clr.red   = mCurBackClrRGB.red + w * ( mTextColor.red - mCurBackClrRGB.red );
  211.         clr.green = mCurBackClrRGB.green + w * ( mTextColor.green - mCurBackClrRGB.green );
  212.         clr.blue  = mCurBackClrRGB.blue + w * ( mTextColor.blue - mCurBackClrRGB.blue );
  213.         
  214.         #if EG_MAC
  215.         ::RGBForeColor( &clr );
  216.         ::MoveTo( mTitleRect.left + 4, mTitleRect.bottom - 4 );
  217.         ::DrawString( str );
  218.         #else
  219.         ::SetTextColor( hdc, __ClrREF( clr ) );
  220.         ::SetBkMode( hdc, TRANSPARENT );
  221.         ::TextOut( hdc, mTitleRect.left + 4, mTitleRect.top, (char*) &str[ 1 ], str[ 0 ] );
  222.         #endif
  223.     }
  224.     else {
  225.         #if EG_MAC
  226.         ::RGBForeColor( &mTextColor );
  227.         ::MoveTo( mTitleRect.left + 4, mTitleRect.bottom - 4 );
  228.         ::DrawString( mWave -> mTitle.getPasStr() );
  229.         #else
  230.         ::SetTextColor( hdc, __ClrREF( mTextColor ) );
  231.         ::SetBkMode( hdc, TRANSPARENT );
  232.         ::TextOut( hdc, mTitleRect.left + 4, mTitleRect.top, mWave -> mTitle.getCStr(), mWave -> mTitle.length() );
  233.         #endif
  234.     }
  235.     
  236.     #if EG_MAC
  237.     // Don't screw up future calls to copybits. Wtf--someone tell my my copyBits() freaks out when
  238.     // the fore color isn't black
  239.     clr.red = clr.green = clr.blue = 0;
  240.     ::RGBForeColor( &clr );
  241.     Point pt;
  242.     ::GetPen( &pt );
  243.     mTitleRect.right = pt.h;
  244.     
  245.     // Restore the prev mac port
  246.     ::SetPort( savePort );
  247.     #endif
  248.     
  249.     #if EG_WIN
  250.     mTitleRect.right = 250; //!!!  ###
  251.     ::ReleaseDC( (HWND) inPort, hdc );
  252.     #endif
  253.  
  254. }
  255.  
  256.  
  257. #define __applySampleToGlobals( s )        mMagPtr = s -> mSample;                                                                                \
  258.                                         mST = .001 * s -> mSampleTime;                                                                        \
  259.                                         mDT = ( (float) ( mLastSampleTime - s -> mSampleTime ) ) / ( (float) mWave -> mSampleDuration );    \
  260.                                         mBass1 = s -> mBass[ 0 ];                                                                            \
  261.                                         mBass2 = s -> mBass[ 1 ];                                                                            \
  262.                                         mBass3 = s -> mBass[ 2 ];
  263.  
  264.  
  265.  
  266. void WhiteCapWorld::Render( long inCurTime, PixPort& inPort, Rect& outDirtyRect ) {
  267.     V3 pt;
  268.     long x, y, curBlurNum, p_x, p_y, i, clrTemp;
  269.     short xorg    = ( mPaneRect.right + mPaneRect.left ) / 2;
  270.     short yorg    = ( mPaneRect.bottom + mPaneRect.top ) / 2;
  271.     R3Matrix T;
  272.     float stepSize, f_x, f_y, f_z;
  273.     Sample* sample;
  274.     long borderXtra;
  275.     RGBColor            curClr;
  276.     long                curWidth, prevWidth;
  277.     bool                transition;
  278.     static ScrnPt        sPt[ NUM_SAMPLE_BINS ];
  279.  
  280.  
  281.     // Calculate the position, direction, and rotation angle of the camera
  282.     mT = ((float) inCurTime ) / 1000.0;
  283.         
  284.     transition = mTransitionTime > 0;
  285.     if ( transition ) {
  286.         f_x = (float) ( mTransitionEnd - inCurTime ) / ( (float) mTransitionTime );
  287.         if ( f_x < 0 )
  288.             f_x = 0;
  289.         mTransitionT = pow( f_x, TRANSITION_ALPHA );
  290.         mWave -> SetupFrame( mNextWave, mTransitionT );
  291.     }
  292.     
  293.     // Before we eval all the "B" exprs, it's possiblle they use the mag() fcn--in B vars,
  294.     // it references the most recent sample.  Warning, if there's no samples available, any B
  295.     // vars that call mag() will get junk. 
  296.     if ( mSamples ) {
  297.         __applySampleToGlobals( mSamples ) }
  298.     else {
  299.         mMagPtr = (float*) sPt; 
  300.         mBass1 = 0;
  301.         mBass2 = 0;
  302.         mBass3 = 0;
  303.     }
  304.  
  305.     // Eval all the "B" exprs        
  306.     mWave -> mB_Var.Evaluate();
  307.     if ( transition )
  308.         mNextWave -> mB_Var.Evaluate();
  309.     
  310.     // Evaluate the current background color
  311.     _evalClr( mCurBackClrRGB.red, mBackR )        
  312.     _evalClr( mCurBackClrRGB.green, mBackG )    
  313.     _evalClr( mCurBackClrRGB.blue, mBackB )
  314.     clrTemp = inPort.SetBackColor( mCurBackClrRGB );
  315.     if ( clrTemp != mCurBackClr ) {
  316.         mCurBackClr = clrTemp;
  317.         mRenderedRect = mPaneRect; 
  318.     }
  319.         
  320.     // The Camera pos
  321.     mCamera.mPos.mX = mWave -> mCamX.Evaluate();
  322.     mCamera.mPos.mY = mWave -> mCamY.Evaluate();
  323.     mCamera.mPos.mZ = mWave -> mCamZ.Evaluate();
  324.     
  325.     // The Camera look direction
  326.     mCamera.mDir.mX = mWave -> mCamLX.Evaluate();
  327.     mCamera.mDir.mY = mWave -> mCamLY.Evaluate();
  328.     mCamera.mDir.mZ = mWave -> mCamLZ.Evaluate();
  329.     mCamera.mDir.subtract( mCamera.mPos );
  330.     
  331.     // The Camera "up" direction
  332.     mCamera.mUpDir.mX = mWave -> mCamUpX.Evaluate();
  333.     mCamera.mUpDir.mY = mWave -> mCamUpY.Evaluate();
  334.     mCamera.mUpDir.mZ = mWave -> mCamUpZ.Evaluate();
  335.     mCamera.mXYScale = mWave -> mXYScale;
  336.  
  337.     // Calc the main transformation matrix, T
  338.     mCamera.CalcTransMatrix( T );
  339.     
  340.     // Erase the area that has stuff drawn on it
  341.     outDirtyRect = mRenderedRect;
  342.     inPort.EraseRect( &mRenderedRect );
  343.     mRenderedRect.top = 5000;        mRenderedRect.left = 5000;
  344.     mRenderedRect.bottom = -5000;    mRenderedRect.right = -5000;
  345.     
  346.     /*
  347.     // Line diagnostic
  348.     for ( float ang = 0; ang < 2*PI; ang += .3 ) {
  349.         x = xorg + 50 * cos( ang + .05 * mT );
  350.         y = yorg - 50 * sin( ang + .05 * mT );
  351.         p_x = xorg + 150 * cos( ang + .05 * mT );
  352.         p_y = yorg - 150 * sin( ang + .05 * mT );
  353.         inPort.SetLineWidth( ang * 2 );
  354.         inPort.Line( x, y, p_x, p_y, 0x000A0A0A );
  355.         inPort.SetLineWidth( 1 );
  356.         inPort.Line( x, y, p_x, p_y, 0x000A000A );
  357.     }
  358.     outDirtyRect.left = xorg - 160;
  359.     outDirtyRect.right = xorg + 160;
  360.     outDirtyRect.top = yorg - 160;
  361.     outDirtyRect.bottom = yorg + 160;
  362.     mRenderedRect = outDirtyRect; 
  363.     return; */
  364.  
  365.  
  366.     // Draw each sample to the screen, starting from the oldest sample
  367.     curBlurNum = mWave -> mNumBlurs;
  368.     
  369.     // This gets bigger when the linewidth gets bigger
  370.     borderXtra = 0;
  371.  
  372.     // Make sure t will never be > 1.0
  373.     discardExpiredRows( inCurTime );
  374.         
  375.     // Cache stuff that gets looked up often
  376.     bool x_depS, y_depS, z_depS, r_depS, g_depS, b_depS;
  377.     x_depS = mWave -> mX_Dep_S;        
  378.     y_depS = mWave -> mY_Dep_S;
  379.     z_depS = mWave -> mZ_Dep_S;
  380.     r_depS = mWave -> mR_Dep_S;        
  381.     g_depS = mWave -> mG_Dep_S;
  382.     b_depS = mWave -> mB_Dep_S;    
  383.     
  384.     
  385.     // This is how many pieces we chop up s's interval from 0 to 1
  386.     stepSize = 1.0 / ( (float) ( mWave -> mNum_S_Steps ) );
  387.  
  388.         
  389.     for ( sample = mSamples; sample; sample = sample -> mNext ) {
  390.         
  391.         // Link mWave.mDict1 to the sample's wave data
  392.         // Assign the delta-time index (in secs) for this sample
  393.         __applySampleToGlobals( sample )
  394.         
  395.         // Evaluate all the "C" expressions
  396.         mWave -> mC_Var.Evaluate();
  397.         if ( transition )
  398.             mNextWave -> mC_Var.Evaluate();
  399.  
  400.         // Calc how wide this sample's linewidth is (round up if > .5)
  401.         prevWidth = curWidth;
  402.         curWidth = ( mWave -> mLineWidth.Evaluate() + 0.5 );
  403.         if ( curWidth > borderXtra )
  404.             borderXtra = curWidth;
  405.         inPort.SetLineWidth( curWidth );
  406.             
  407.         // Evaluate vars that are indep of S (or D)
  408.         if ( ! x_depS )    f_x = mWave -> mX.Evaluate() - mCamera.mPos.mX;
  409.         if ( ! y_depS )    f_y = mWave -> mY.Evaluate() - mCamera.mPos.mY;
  410.         if ( ! z_depS )    f_z = mWave -> mZ.Evaluate() - mCamera.mPos.mZ;
  411.         if ( ! r_depS )    _evalClr( curClr.red, mR )
  412.         if ( ! g_depS )    _evalClr( curClr.green, mG )
  413.         if ( ! b_depS )    _evalClr( curClr.blue, mB )
  414.         
  415.         // Draw the old samples to the new ones
  416.         for ( mS = 0, i = 0; i < mWave -> mNum_S_Steps; i++, mS += stepSize ) {
  417.             
  418.             // Evaluate all the "D" expressions
  419.             mWave -> mD_Var.Evaluate();
  420.             if ( transition )
  421.                 mNextWave -> mD_Var.Evaluate();
  422.  
  423.             // Only evaluate expressions that are dependent on S
  424.             pt.mX = ( x_depS ) ? mWave -> mX.Evaluate() - mCamera.mPos.mX : f_x;
  425.             pt.mY = ( y_depS ) ? mWave -> mY.Evaluate() - mCamera.mPos.mY : f_y;
  426.             pt.mZ = ( z_depS ) ? mWave -> mZ.Evaluate() - mCamera.mPos.mZ : f_z;
  427.             pt.transform( T, mWave -> mPerspectiveInt );
  428.             p_x = xorg + pt.mX;
  429.             p_y = yorg - pt.mY;
  430.                 
  431.             // Calc the screen pt and update out bounds rectangle
  432.             __Chk( p_x, p_y )
  433.     
  434.             // Calculate the color for this point
  435.             if ( r_depS )    _evalClr( curClr.red, mR )
  436.             if ( g_depS )    _evalClr( curClr.green, mG )
  437.             if ( b_depS )    _evalClr( curClr.blue, mB )
  438.                         
  439.             // Are we supposed to connect to the prev sample?  Also catch when we're drawin the first sample
  440.             if ( mWave -> mConnectSamples ) {
  441.                 if ( sample != mSamples ) {
  442.                     if ( sample -> mNext )
  443.                         inPort.Line( sPt[ i ].x, sPt[ i ].y, p_x, p_y, sPt[ i ].color, curClr );
  444.                     else {
  445.                         inPort.SetLineWidth( prevWidth );
  446.                         inPort.Line( sPt[ i ].x, sPt[ i ].y, p_x, p_y, sPt[ i ].color, curClr );
  447.                         inPort.SetLineWidth( curWidth );
  448.                     }
  449.                 }
  450.             }
  451.             
  452.             // Record key scrn info for current sample
  453.             sPt[ i ].x = p_x;
  454.             sPt[ i ].y = p_y;
  455.             
  456.             // Evaluate the level color (if it was given)
  457.             if ( sample -> mNext )
  458.                 sPt[ i ].color = curClr;
  459.             else {
  460.                 _evalClr( sPt[ i ].color.red, mLvlR )
  461.                 _evalClr( sPt[ i ].color.green, mLvlG )
  462.                 _evalClr( sPt[ i ].color.blue, mLvlB )
  463.             }
  464.  
  465.             // If we're connecting bins...
  466.             if ( mWave -> mConnectBins && i > 0 )
  467.                 inPort.Line( p_x, p_y, sPt[ i - 1 ].x, sPt[ i - 1 ].y, sPt[ i ].color, sPt[ i - 1 ].color );
  468.         
  469.             // If we're just drawing dots...    (we can skip drawing dots if samples are already connected)        
  470.             else if ( ! mWave -> mConnectSamples || ! sample -> mNext )
  471.                 inPort.Line( p_x, p_y, p_x, p_y, sPt[ i ].color, sPt[ i ].color );
  472.         }
  473.         
  474.         // Connect bin 0 and bin N is user wants it
  475.         if ( mWave -> mConnectFirstLast ) {
  476.             curClr = sPt[ mWave -> mNum_S_Steps - 1 ].color;
  477.             inPort.Line( p_x, p_y, sPt[ 0 ].x, sPt[ 0 ].y, curClr, curClr );
  478.         }
  479.         
  480.         // Do the blur if the number of blurs is valid
  481.         if ( mWave -> mNumBlurs > 0 ) {
  482.             float t_scale = 1000.0 * mDT / mWave -> mSampleDuration;
  483.             if ( t_scale <= ( (float) curBlurNum - 1.0) / mWave -> mNumBlurs ) {
  484.                 ::InsetRect( &mRenderedRect, - borderXtra - 3, - borderXtra - 3 );
  485.                 inPort.GaussBlur( mWave -> mBlurVal, mRenderedRect, NULL );
  486.                 curBlurNum--;
  487.             }    
  488.         }
  489.     }
  490.     
  491.     // We'll let the text color be the color of the s == 1 side of the level
  492.     if ( mSamples )
  493.         mTextColor = sPt[ 0 ].color;
  494.     else {
  495.         // cosmetic prob: when we don't have any samples, we don't have a clr for the text.
  496.         // What do we do?  for now, we'll just use the text color as the last from (bad)
  497.     }
  498.  
  499.     // If we've just finished a transition, end it
  500.     if ( transition && inCurTime > mTransitionEnd ) {
  501.         WC_WaveShape* temp = mWave;
  502.         mWave = mNextWave;
  503.         mNextWave = temp;
  504.         mTransitionTime = -1;
  505.         mRenderedRect = mPaneRect;        // Refresh everthing
  506.     }
  507.     
  508.     // Things like line widths > 1 may have drawn a little outside our bounds rect
  509.     ::InsetRect( &mRenderedRect, -borderXtra - 1, -borderXtra - 1 );
  510.     
  511.     // The area we have to refresh either has new bits or old bits
  512.     ::UnionRect( &mRenderedRect, &outDirtyRect, &outDirtyRect );
  513.     
  514.     // Limit the refresh rect to our pane
  515.     ::SectRect( &mPaneRect, &outDirtyRect, &outDirtyRect );
  516. }
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523. void WhiteCapWorld::RefreshRect( const Rect& inRect ) {
  524.     Rect r;
  525.     
  526.     // Clip the rect to this pane
  527.     ::SectRect( &mPaneRect, &inRect, &r );
  528.  
  529.     
  530.     // Make sure we erase that part of the window next time
  531.     ::UnionRect( &mRenderedRect, &r, &mRenderedRect );
  532. }
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539. void WhiteCapWorld::RecordSample( long inCurTime, const float inSpectrum[] ) {
  540.     Sample* sample;
  541.             
  542.     // Store the newest sample, don't store anything if its less than our time resolution
  543.     if ( inCurTime - mLastSampleTime > mWave -> mSampleDelay ) {
  544.  
  545.         // Get a free sample structure
  546.         if ( mFreeList.FetchLast( &sample ) ) 
  547.             mFreeList.RemoveLast(); 
  548.         else 
  549.             sample = new Sample();
  550.             
  551.         // Maintain our list of samples
  552.         sample -> mNext = NULL;
  553.         if ( mRecentSample ) 
  554.             mRecentSample -> mNext = sample;
  555.         else 
  556.             mSamples = sample;
  557.             
  558.         // Set the sample's data
  559.         sample -> Assign( inCurTime, inSpectrum, mRecentSample, mWave -> mFalloff );
  560.         
  561.         // Update "current" sample shortcuts
  562.         mRecentSample = sample;        
  563.         mLastSampleTime = inCurTime;
  564.     }
  565. }
  566.  
  567.  
  568.  
  569.  
  570. void WhiteCapWorld::discardExpiredRows( long inCurTime ) {
  571.     long dur = mWave -> mSampleDuration;
  572.     Sample* sample = mSamples;
  573.     
  574.     while ( sample ) {
  575.         
  576.         // Step from old to newer samples, discarding until we don't have old samples
  577.         if ( sample -> TimeOfSample() + dur < inCurTime ) {
  578.             if ( sample == mRecentSample )
  579.                 mRecentSample = NULL;
  580.             mFreeList.Add( sample );
  581.             sample = sample -> mNext;
  582.             mSamples = sample; }
  583.         else
  584.             sample = NULL;
  585.     }
  586. }
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594. void WhiteCapWorld::ExpireSamples() {
  595.     Sample* sample = mSamples;
  596.  
  597.     while ( sample ) {
  598.         mFreeList.Add( sample );
  599.         sample = sample -> mNext;
  600.     }
  601.  
  602.     mSamples        = NULL;
  603.     mRecentSample    = NULL;
  604. }
  605.  
  606.     
  607.  
  608.  
  609.  
  610.